home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / The World of Computer Software.iso / winsr173.zip / WINTEXT.C < prev    next >
C/C++ Source or Header  |  1992-05-25  |  24KB  |  746 lines

  1. #include <windows.h>
  2. #include <string.h>
  3. #include <stdlib.h>
  4.  
  5. /*
  6.     WINTEXT.C handles the character-based "prompt screens",
  7.     using a 24x80 character-window driver that I wrote originally
  8.     for the Windows port of the DOS-based "Screen Generator"
  9.     commercial package - Bert Tyler
  10.  
  11.     the subroutines and their functions are:
  12.  
  13. BOOL wintext_initialize(HANDLE hInstance, LPSTR title);
  14.     Registers and initializes the text window - must be called
  15.     once (and only once).  Its parameters are the handle of the application
  16.     instance and a pointer to a string containing the title of the window.
  17. void wintext_destroy();
  18.     Destroys items like bitmaps that the initialization routine has
  19.     created.  Should be called once (and only once) as your program exits.
  20.  
  21. int wintext_texton();
  22.     Brings up and blanks out the text window.  No parameters.
  23. int wintext_textoff();
  24.     Removes the text window.  No parameters.
  25.  
  26. void wintext_putstring(int xpos, int ypos, int attrib, char far *string);
  27.     Sends a character string to the screen starting at (xpos, ypos)
  28.     using the (CGA-style and, yes, it should be a 'char') specified attribute. 
  29. void wintext_paintscreen(int xmin, int xmax, int ymin, int ymax);
  30.     Repaints the rectangular portion of the text screen specified by
  31.     the four parameters, which are in character co-ordinates.  This
  32.     routine is called automatically by 'wintext_putstring()' as well as
  33.     other internal routines whenever Windows uncovers the window.  It can
  34.     also be called  manually by your program when it wants a portion
  35.     of the screen updated (the actual data is kept in two arrays, which
  36.     your program has presumably updated:)
  37.        unsigned char far wintext_chars[25][80]  holds the text
  38.        unsigned char far wintext_attrs[25][80]  holds the (CGA-style) attributes
  39.  
  40. void wintext_cursor(int xpos, int ypos, int cursor_type);
  41.     Sets the cursor to character position (xpos, ypos) and switches to
  42.     a cursor type specified by 'cursor_type': 0 = none, 1 = underline,
  43.     2 = block cursor.  A cursor type of -1 means use whatever cursor
  44.     type (0, 1, or 2) was already active.
  45.  
  46. unsigned int wintext_getkeypress(int option);
  47.     A simple keypress-retriever that, based on the parameter, either checks
  48.     for any keypress activity (option = 0) or waits for a keypress before
  49.     returning (option != 0).  Returns a 0 to indicate no keystroke, or the
  50.     keystroke itself.  Up to 80 keystrokes are queued in an internal buffer.
  51.     If the text window is not open, returns an ESCAPE keystroke (27).
  52.     The keystroke is returned as an integer value identical to that a
  53.     DOS program receives in AX when it invokes INT 16H, AX = 0 or 1.
  54.  
  55. int wintext_look_for_activity(int option);
  56.     An internal routine that handles buffered keystrokes and lets
  57.     Windows messaging (multitasking) take place.  Called with option=0,
  58.     it returns without waiting for the presence of a keystroke.  Called
  59.     with option !=0, it waits for a keystroke before returning.  Returns
  60.     1 if a keystroke is pending, 0 if none pending.  Called internally
  61.     (and automatically) by 'wintext_getkeypress()'.
  62. void wintext_addkeypress(unsigned int);
  63.     An internal routine, called by 'wintext_look_for_activity()' and
  64.     'wintext_proc()', that adds keystrokes to an internal buffer.
  65.     Never called directly by the applications program.
  66. long FAR PASCAL wintext_proc(HANDLE, unsigned, WORD, LONG);
  67.     An internal routine that handles all message functions while
  68.     the text window is on the screen.  Never called directly by
  69.     the applications program, but must be referenced as a call-back
  70.     routine by your ".DEF" file.
  71.  
  72.     The 'wintext_textmode' flag tracks the current textmode status.
  73.     Note that pressing Alt-F4 closes and destroys the window *and*
  74.     resets this flag (to 1), so the main program should look at
  75.     this flag whenever it is possible that Alt-F4 has been hit!
  76.     ('wintext_getkeypress()' returns a 27 (ESCAPE) if this happens)
  77.     (Note that you can use an 'WM_CLOSE' case to handle this situation.)
  78.         The 'wintext_textmode' values are:
  79.             0 = the initialization routine has never been called!
  80.             1 = text mode is *not* active
  81.             2 = text mode *is* active
  82.     There is also a 'wintext_AltF4hit' flag that is non-zero if
  83.     the window has been closed (by an Alt-F4, or a WM_CLOSE sequence)
  84.     but the application program hasn't officially closed the window yet.
  85. */
  86.  
  87. int far wintext_textmode = 0;
  88. int far wintext_AltF4hit = 0;
  89.  
  90. /* function prototypes */
  91.  
  92. BOOL wintext_initialize(HANDLE, HWND, LPSTR);
  93. void wintext_destroy();
  94. long FAR PASCAL wintext_proc(HANDLE, unsigned, WORD, LONG);
  95. int wintext_texton();
  96. int wintext_textoff();
  97. void wintext_putstring(int xpos, int ypos, int attrib, char far *string);
  98. void wintext_paintscreen(int, int, int, int);
  99. void wintext_cursor(int, int, int);
  100. int wintext_look_for_activity(int);
  101. void wintext_addkeypress(unsigned int);
  102. unsigned int wintext_getkeypress(int);
  103.  
  104. /* Local copy of the "screen" characters and attributes */
  105.  
  106. unsigned char far wintext_chars[25][80];
  107. unsigned char far wintext_attrs[25][80];
  108. int far wintext_buffer_init;     /* zero if 'screen' is uninitialized */
  109.  
  110. /* font information */
  111.  
  112. HFONT far wintext_hFont;
  113. int far wintext_char_font;
  114. int far wintext_char_width;
  115. int far wintext_char_height;
  116. int far wintext_char_xchars;
  117. int far wintext_char_ychars;
  118. int far wintext_max_width;
  119. int far wintext_max_height;
  120.  
  121. /* "cursor" variables (AKA the "caret" in Window-Speak) */
  122. int far wintext_cursor_x;
  123. int far wintext_cursor_y;
  124. int far wintext_cursor_type;
  125. int far wintext_cursor_owned;
  126. HBITMAP far wintext_bitmap[3];
  127. short far wintext_cursor_pattern[3][40];
  128.  
  129. LPSTR wintext_title_text;         /* title-bar text */
  130.  
  131. /* a few Windows variables we need to remember globally */
  132.  
  133. HWND far wintext_hWndCopy;                /* a Global copy of hWnd */
  134. HWND far wintext_hWndParent;              /* a Global copy of hWnd's Parent */
  135. HANDLE far wintext_hInstance;             /* a global copy of hInstance */
  136.  
  137. /* the keypress buffer */
  138.  
  139. #define BUFMAX 80
  140. unsigned int  far wintext_keypress_count;
  141. unsigned int  far wintext_keypress_head;
  142. unsigned int  far wintext_keypress_tail;
  143. unsigned char far wintext_keypress_initstate;
  144. unsigned int  far wintext_keypress_buffer[BUFMAX];
  145. unsigned char far wintext_keypress_state[BUFMAX];
  146.  
  147. /* EGA/VGA 16-color palette (which doesn't match Windows palette exactly) */
  148. /*
  149. COLORREF wintext_color[] = {
  150.     RGB(0,0,0),
  151.     RGB(0,0,168),
  152.     RGB(0,168,0),
  153.     RGB(0,168,168),
  154.     RGB(168,0,0),
  155.     RGB(168,0,168),
  156.     RGB(168,84,0),
  157.     RGB(168,168,168),
  158.     RGB(84,84,84),
  159.     RGB(84,84,255),
  160.     RGB(84,255,84),
  161.     RGB(84,255,255),
  162.     RGB(255,84,84),
  163.     RGB(255,84,255),
  164.     RGB(255,255,84),
  165.     RGB(255,255,255)
  166.     };
  167. */
  168. /* 16-color Windows Palette */
  169.  
  170. COLORREF wintext_color[] = {
  171.     RGB(0,0,0),
  172.     RGB(0,0,128),
  173.     RGB(0,128,0),
  174.     RGB(0,128,128),
  175.     RGB(128,0,0),
  176.     RGB(128,0,128),
  177.     RGB(128,128,0),
  178.     RGB(192,192,192),
  179. /*  RGB(128,128,128),  This looks lousy - make it black */  RGB(0,0,0),
  180.     RGB(0,0,255),
  181.     RGB(0,255,0),
  182.     RGB(0,255,255),
  183.     RGB(255,0,0),
  184.     RGB(255,0,255),
  185.     RGB(255,255,0),
  186.     RGB(255,255,255)
  187.     };
  188.  
  189. /*
  190.      Register the text window - a one-time function which perfomrs
  191.      all of the neccessary registration and initialization
  192. */
  193.  
  194. BOOL wintext_initialize(HANDLE hInstance, HWND hWndParent, LPSTR titletext)
  195. {
  196.     WNDCLASS  wc;
  197.     BOOL return_value;
  198.     HDC hDC;
  199.     HFONT hOldFont;
  200.     TEXTMETRIC TextMetric;
  201.     int i, j;
  202.  
  203.     wintext_hInstance = hInstance;
  204.     wintext_title_text = titletext;
  205.     wintext_hWndParent = hWndParent;
  206.  
  207.     wc.style = NULL;
  208.     wc.lpfnWndProc = wintext_proc;
  209.     wc.cbClsExtra = 0;
  210.     wc.cbWndExtra = 0;
  211.     wc.hInstance = hInstance;
  212.     wc.hIcon = NULL;
  213.     wc.hCursor = LoadCursor(NULL, IDC_ARROW);
  214.     wc.hbrBackground = GetStockObject(BLACK_BRUSH);
  215.     wc.lpszMenuName =  titletext;
  216.     wc.lpszClassName = "FractintForWindowsV0011";
  217.  
  218.     return_value = RegisterClass(&wc);
  219.  
  220.     /* set up the font characteristics */
  221.     wintext_char_font = OEM_FIXED_FONT;
  222.     wintext_hFont = GetStockObject(wintext_char_font);
  223.     hDC=GetDC(hWndParent);
  224.     hOldFont = SelectObject(hDC, wintext_hFont);
  225.     GetTextMetrics(hDC, &TextMetric);
  226.     SelectObject(hDC, hOldFont);
  227.     ReleaseDC(hWndParent, hDC);
  228.     wintext_char_width  = TextMetric.tmMaxCharWidth;
  229.     wintext_char_height = TextMetric.tmHeight;
  230.     wintext_char_xchars = 80;
  231.     wintext_char_ychars = 25;
  232.  
  233.     wintext_max_width =                           /* maximum screen width */
  234.         wintext_char_xchars*wintext_char_width+
  235.             (GetSystemMetrics(SM_CXFRAME) * 2);
  236.     wintext_max_height =                           /* maximum screen height */
  237.         wintext_char_ychars*wintext_char_height+
  238.             (GetSystemMetrics(SM_CYFRAME) * 2)
  239.             -1
  240.              + GetSystemMetrics(SM_CYCAPTION);
  241.  
  242.     /* set up the font and caret information */
  243.     for (i = 0; i < 3; i++)
  244.         for (j = 0; j < wintext_char_height; j++)
  245.             wintext_cursor_pattern[i][j] = 0;
  246.     for (j = wintext_char_height-2; j < wintext_char_height; j++)
  247.         wintext_cursor_pattern[1][j] = 0x00ff;
  248.     for (j = 0; j < wintext_char_height; j++)
  249.         wintext_cursor_pattern[2][j] = 0x00ff;
  250.     wintext_bitmap[0] = CreateBitmap(8, wintext_char_height, 1, 1,
  251.         (LPSTR)wintext_cursor_pattern[0]);
  252.     wintext_bitmap[1] = CreateBitmap(8, wintext_char_height, 1, 1,
  253.         (LPSTR)wintext_cursor_pattern[1]);
  254.     wintext_bitmap[2] = CreateBitmap(8, wintext_char_height, 1, 1,
  255.         (LPSTR)wintext_cursor_pattern[2]);
  256.  
  257.     wintext_textmode = 1;
  258.     wintext_AltF4hit = 0;
  259.  
  260.     return(return_value);
  261. }
  262.  
  263. /*
  264.     clean-up routine
  265. */
  266. void wintext_destroy()
  267. {
  268. int i;
  269.  
  270.     if (wintext_textmode == 2)  /* text is still active! */
  271.         wintext_textoff();
  272.     if (wintext_textmode != 1)  /* not in the right mode */
  273.         return;
  274.  
  275. /*
  276.     DeleteObject((HANDLE)wintext_hFont);
  277. */
  278.     for (i = 0; i < 3; i++)
  279.         DeleteObject((HANDLE)wintext_bitmap[i]);
  280.     wintext_textmode = 0;
  281.     wintext_AltF4hit = 0;
  282. }
  283.  
  284.  
  285. /*
  286.      Set up the text window and clear it
  287. */
  288.  
  289. int wintext_texton()
  290. {
  291.     HWND hWnd;
  292.     int i, j, k;
  293.  
  294.     if (wintext_textmode != 1)  /* not in the right mode */
  295.         return(0);
  296.  
  297.     /* initialize the cursor */
  298.     wintext_cursor_x    = 0;
  299.     wintext_cursor_y    = 0;
  300.     wintext_cursor_type = 0;
  301.     wintext_cursor_owned = 0;
  302.  
  303.     /* clear the keyboard buffer */
  304.     wintext_keypress_count = 0;
  305.     wintext_keypress_head  = 0;
  306.     wintext_keypress_tail  = 0;
  307.     wintext_keypress_initstate = 0;
  308.     wintext_buffer_init = 0;
  309.  
  310.     hWnd = CreateWindow(
  311.         "FractintForWindowsV0011",
  312.         wintext_title_text,
  313.         WS_OVERLAPPEDWINDOW,
  314.         CW_USEDEFAULT,               /* default horizontal position */
  315.         CW_USEDEFAULT,               /* default vertical position */
  316.         wintext_max_width,
  317.         wintext_max_height,
  318.         wintext_hWndParent,
  319.         NULL,
  320.         wintext_hInstance,
  321.         NULL);
  322.  
  323.     /* squirrel away a global copy of 'hWnd' for later */
  324.     wintext_hWndCopy = hWnd;
  325.  
  326.     wintext_textmode = 2;
  327.     wintext_AltF4hit = 0;
  328.  
  329.     ShowWindow(wintext_hWndCopy, SW_SHOWNORMAL);
  330.     UpdateWindow(wintext_hWndCopy);
  331.  
  332.     InvalidateRect(wintext_hWndCopy,NULL,FALSE);
  333.  
  334.     return(0);
  335. }
  336.  
  337. /*
  338.      Remove the text window
  339. */
  340.  
  341. int wintext_textoff()
  342. {
  343.  
  344.     wintext_AltF4hit = 0;
  345.     if (wintext_textmode != 2)  /* not in the right mode */
  346.         return(0);
  347.     DestroyWindow(wintext_hWndCopy);
  348.     wintext_textmode = 1;
  349.     return(0);
  350. }
  351.  
  352. /*
  353.     Window-handling procedure
  354. */
  355.  
  356.  
  357. long FAR PASCAL wintext_proc(hWnd, message, wParam, lParam)
  358. HWND hWnd;
  359. unsigned message;
  360. WORD wParam;
  361. LONG lParam;
  362. {
  363.     RECT tempRect;
  364.     PAINTSTRUCT ps;
  365.     HDC hDC;
  366.  
  367.     if (hWnd != wintext_hWndCopy)  /* ??? not the text-mode window! */
  368.          return (DefWindowProc(hWnd, message, wParam, lParam));
  369.  
  370.     switch (message) {
  371.  
  372.         case WM_INITMENU:
  373.            /* first time through*/
  374.            /* someday we might want to do something special here */
  375.            return (TRUE);
  376.  
  377.      case WM_COMMAND:
  378.          /* if we added menu items, they would go here */
  379.          return (DefWindowProc(hWnd, message, wParam, lParam));
  380.  
  381.      case WM_CLOSE:
  382.          wintext_textmode = 1;
  383.          wintext_AltF4hit = 1;
  384.          return (DefWindowProc(hWnd, message, wParam, lParam));
  385.  
  386.         case WM_SIZE:
  387.             /* code to prevent the window from exceeding a "full text page" */
  388.             if (LOWORD(lParam) > wintext_max_width ||
  389.                 HIWORD(lParam) > wintext_max_height)
  390.                 SetWindowPos(wintext_hWndCopy,
  391.                    GetNextWindow(wintext_hWndCopy, GW_HWNDPREV),
  392.                    0, 0, wintext_max_width, wintext_max_height, SWP_NOMOVE);
  393.             break;
  394.  
  395.      case WM_SETFOCUS : /* get focus - display caret */
  396.           /* create caret & display */
  397.           wintext_cursor_owned = 1;
  398.           CreateCaret( wintext_hWndCopy, wintext_bitmap[wintext_cursor_type],
  399.               wintext_char_width, wintext_char_height);
  400.           SetCaretPos( wintext_cursor_x*wintext_char_width,
  401.               wintext_cursor_y*wintext_char_height);
  402.                 SetCaretBlinkTime(500);
  403.                 ShowCaret( wintext_hWndCopy );
  404.           break;
  405.  
  406.      case WM_KILLFOCUS : /* kill focus - hide caret */
  407.           wintext_cursor_owned = 0;
  408.           DestroyCaret();
  409.           break;
  410.  
  411.        case WM_PAINT:  /* "Paint" routine - call the worker routine */
  412.             hDC = BeginPaint(hWnd, &ps);
  413.             GetUpdateRect(hWnd, &tempRect, FALSE);
  414.             ValidateRect(hWnd, &tempRect);
  415.             /* the routine below handles *all* window updates */
  416.             wintext_paintscreen(0, wintext_char_xchars-1, 0, wintext_char_ychars-1);
  417.             EndPaint(hWnd, &ps);
  418.             break;
  419.  
  420.        case WM_KEYDOWN:   /* KEYUP, KEYDOWN, and CHAR msgs go to the 'keypressed' code */
  421.             /* a key has been pressed - maybe ASCII, maybe not */
  422.             /* if it's an ASCII key, 'WM_CHAR' will handle it  */
  423.             {
  424.             unsigned int i, j, k;
  425.             i = (MapVirtualKey(wParam,0));
  426.             j = (MapVirtualKey(wParam,2));
  427.             k = (i << 8) + j;
  428.             if (wParam == 0x10 || wParam == 0x11) { /* shift or ctl key */
  429.                 j = 0;       /* send flag: special key down */
  430.                 k = 0xff00 + wParam;
  431.                 }
  432.             if (j == 0)        /* use this call only for non-ASCII keys */
  433.                 wintext_addkeypress(k);
  434.             }
  435.             break;
  436.  
  437.        case WM_KEYUP:   /* KEYUP, KEYDOWN, and CHAR msgs go to the SG code */
  438.             /* a key has been released - maybe ASCII, maybe not */
  439.             /* Watch for Shift, Ctl keys  */
  440.             {
  441.             unsigned int i, j, k;
  442.             i = (MapVirtualKey(wParam,0));
  443.             j = (MapVirtualKey(wParam,2));
  444.             k = (i << 8) + j;
  445.             j = 1;
  446.             if (wParam == 0x10 || wParam == 0x11) { /* shift or ctl key */
  447.                 j = 0;       /* send flag: special key up */
  448.                 k = 0xfe00 + wParam;
  449.                 }
  450.             if (j == 0)        /* use this call only for non-ASCII keys */
  451.                 wintext_addkeypress(k);
  452.             }
  453.             break;
  454.  
  455.        case WM_CHAR:   /* KEYUP, KEYDOWN, and CHAR msgs go to the SG code */
  456.             /* an ASCII key has been pressed */
  457.             {
  458.             unsigned int i, j, k;
  459.             i = (lParam & 0x00ff0000) >> 16;
  460.             j = wParam;
  461.             k = (i << 8) + j;
  462.             wintext_addkeypress(k);
  463.             }
  464.             break;
  465.  
  466.      default:
  467.          return (DefWindowProc(hWnd, message, wParam, lParam));
  468.     }
  469.     return (NULL);
  470. }
  471.  
  472. /*
  473.      simple keyboard logic capable of handling 80
  474.      typed-ahead keyboard characters (more, if BUFMAX is changed)
  475.           wintext_addkeypress() inserts a new keypress
  476.           wintext_getkeypress(0) returns keypress-available info
  477.           wintext_getkeypress(1) takes away the oldest keypress
  478. */
  479.  
  480. void wintext_addkeypress(unsigned int keypress)
  481. {
  482.  
  483. if (wintext_textmode != 2)  /* not in the right mode */
  484.     return;
  485.  
  486. if (wintext_keypress_count >= BUFMAX)
  487.     /* no room */
  488.     return;
  489.  
  490. if ((keypress & 0xfe00) == 0xfe00) {
  491.     if (keypress == 0xff10) wintext_keypress_initstate |= 0x01;
  492.     if (keypress == 0xfe10) wintext_keypress_initstate &= 0xfe;
  493.     if (keypress == 0xff11) wintext_keypress_initstate |= 0x02;
  494.     if (keypress == 0xfe11) wintext_keypress_initstate &= 0xfd;
  495.     return;
  496.     }
  497.  
  498. if (wintext_keypress_initstate != 0) {              /* shift/ctl key down */
  499.     if ((wintext_keypress_initstate & 1) != 0) {    /* shift key down */
  500.         if ((keypress & 0x00ff) == 9)             /* TAB key down */
  501.                 keypress = (15 << 8);             /* convert to shift-tab */
  502.         if ((keypress & 0x00ff) == 0) {           /* special character */
  503.             int i;
  504.             i = (keypress >> 8) & 0xff;
  505.             if (i >= 59 && i <= 68)               /* F1 thru F10 */
  506.                 keypress = ((i + 25) << 8);       /* convert to Shifted-Fn */
  507.             }
  508.         }
  509.     else {                                        /* control key down */
  510.         if ((keypress & 0x00ff) == 0) {           /* special character */
  511.             int i;
  512.             i = ((keypress & 0xff00) >> 8);
  513.             if (i >= 59 && i <= 68)               /* F1 thru F10 */
  514.                 keypress = ((i + 35) << 8);       /* convert to Ctl-Fn */
  515.             if (i == 71)
  516.                 keypress = (119 << 8);
  517.             if (i == 73)
  518.                 keypress = (132 << 8);
  519.             if (i == 75)
  520.                 keypress = (115 << 8);
  521.             if (i == 77)
  522.                 keypress = (116 << 8);
  523.             if (i == 79)
  524.                 keypress = (117 << 8);
  525.             if (i == 81)
  526.                 keypress = (118 << 8);
  527.             }
  528.         }
  529.     }
  530.  
  531. wintext_keypress_buffer[wintext_keypress_head] = keypress;
  532. wintext_keypress_state[wintext_keypress_head] = wintext_keypress_initstate;
  533. if (++wintext_keypress_head >= BUFMAX)
  534.     wintext_keypress_head = 0;
  535. wintext_keypress_count++;
  536. }
  537.  
  538. unsigned int wintext_getkeypress(int option)
  539. {
  540. int i;
  541.  
  542. wintext_look_for_activity(option);
  543.  
  544. if (wintext_textmode != 2)  /* not in the right mode */
  545.     return(27);
  546.  
  547. if (wintext_keypress_count == 0)
  548.     return(0);
  549.  
  550. i = wintext_keypress_buffer[wintext_keypress_tail];
  551.  
  552. if (option != 0) {
  553.     if (++wintext_keypress_tail >= BUFMAX)
  554.         wintext_keypress_tail = 0;
  555.     wintext_keypress_count--;
  556.     }
  557.  
  558. return(i);
  559.  
  560. }
  561.  
  562.  
  563. /*
  564.      simple event-handler and look-for-keyboard-activity process
  565.  
  566.      called with parameter:
  567.           0 = tell me if a key was pressed
  568.           1 = wait for a keypress
  569.      returns:
  570.           0 = no activity
  571.           1 = key pressed
  572. */
  573.  
  574. int wintext_look_for_activity(int wintext_waitflag)
  575. {
  576. MSG msg;
  577. int i;
  578.  
  579. if (wintext_textmode != 2)  /* not in the right mode */
  580.     return(0);
  581.  
  582. for (;;) {
  583.     if (PeekMessage(&msg, NULL, NULL, NULL, PM_NOREMOVE) == 0)
  584.         if (wintext_waitflag == 0 || wintext_keypress_count != 0
  585.             || wintext_textmode != 2)
  586.             return(wintext_keypress_count == 0 ? 0 : 1);
  587.  
  588.     if (GetMessage(&msg, NULL, NULL, NULL)) {
  589.         TranslateMessage(&msg);
  590.         DispatchMessage(&msg);
  591.         }
  592.     }
  593.  
  594. return(wintext_keypress_count == 0 ? 0 : 1);
  595.  
  596. }
  597.  
  598. /*
  599.     general routine to send a string to the screen
  600. */
  601.  
  602. void wintext_putstring(int xpos, int ypos, int attrib, char far *string)
  603. {
  604.     int i, j, k, maxrow, maxcol;
  605.     char xc, xa;
  606.  
  607.     xa = (attrib & 0x0ff);
  608.     j = maxrow = ypos;
  609.     k = maxcol = xpos-1;
  610.  
  611.     for (i = 0; (xc = string[i]) != 0; i++) {
  612.         if (xc == 13 || xc == 10) {
  613.             if (j < 24) j++;
  614.             k = -1;
  615.             }
  616.         else {
  617.             if ((++k) >= 80) {
  618.                 if (j < 24) j++;
  619.                 k = 0;
  620.                 }
  621.             if (maxrow < j) maxrow = j;
  622.             if (maxcol < k) maxcol = k;
  623.             wintext_chars[j][k] = xc;
  624.             wintext_attrs[j][k] = xa;
  625.             }
  626.         }
  627.     if (i > 0) {
  628.         wintext_paintscreen(xpos, maxcol, ypos, maxrow);
  629.         }
  630. }
  631.  
  632. /*
  633.      general routine to repaint the screen
  634. */
  635.  
  636. void wintext_paintscreen(
  637.     int xmin,       /* update this rectangular section */
  638.     int xmax,       /* of the 'screen'                 */
  639.     int ymin,
  640.     int ymax)
  641. {
  642. int i, j, k;
  643. int istart, jstart, length, foreground, background;
  644. unsigned char wintext_oldbk;
  645. unsigned char wintext_oldfg;
  646. HDC hDC;
  647. HWND hWnd;
  648.  
  649. if (wintext_textmode != 2)  /* not in the right mode */
  650.     return;
  651.  
  652. /* first time through?  Initialize the 'screen' */
  653. if (wintext_buffer_init == 0) {
  654.     wintext_buffer_init = 1;
  655.     wintext_oldbk = 0x00;
  656.     wintext_oldfg = 0x0f;
  657.     k = (wintext_oldbk << 4) + wintext_oldfg;
  658.     wintext_buffer_init = 1;
  659.     for (i = 0; i < wintext_char_xchars; i++) {
  660.         for (j = 0; j < wintext_char_ychars; j++) {
  661.             wintext_chars[j][i] = ' ';
  662.             wintext_attrs[j][i] = k;
  663.             }
  664.         }
  665.     }
  666.  
  667. if (xmin < 0) xmin = 0;
  668. if (xmax >= wintext_char_xchars) xmax = wintext_char_xchars-1;
  669. if (ymin < 0) ymin = 0;
  670. if (ymax >= wintext_char_ychars) ymax = wintext_char_ychars-1;
  671.  
  672. hDC=GetDC(wintext_hWndCopy);
  673. SelectObject(hDC, wintext_hFont);
  674. SetBkMode(hDC, OPAQUE);
  675. SetTextAlign(hDC, TA_LEFT | TA_TOP);
  676.  
  677. if (wintext_cursor_owned != 0)
  678.     HideCaret( wintext_hWndCopy );
  679.  
  680. /*
  681.    the following convoluted code minimizes the number of
  682.    discrete calls to the Windows interface by locating
  683.    'strings' of screen locations with common foreground
  684.    and background colors
  685. */
  686.  
  687. for (j = ymin; j <= ymax; j++) {
  688.     length = 0;
  689.     wintext_oldbk = 99;
  690.     wintext_oldfg = 99;
  691.     for (i = xmin; i <= xmax+1; i++) {
  692.         k = -1;
  693.         if (i <= xmax)
  694.             k = wintext_attrs[j][i];
  695.         foreground = (k & 15);
  696.         background = (k >> 4);
  697.         if (i > xmax || foreground != wintext_oldfg || background != wintext_oldbk) {
  698.             if (length > 0) {
  699.                 SetBkColor(hDC,wintext_color[wintext_oldbk]);
  700.                 SetTextColor(hDC,wintext_color[wintext_oldfg]);
  701.                 TextOut(hDC,
  702.                     istart*wintext_char_width,
  703.                     jstart*wintext_char_height,
  704.                     &wintext_chars[jstart][istart],
  705.                     length);
  706.                 }
  707.             wintext_oldbk = background;
  708.             wintext_oldfg = foreground;
  709.          istart = i;
  710.          jstart = j;
  711.          length = 0;
  712.             }
  713.         length++;
  714.         }
  715.     }
  716.  
  717. if (wintext_cursor_owned != 0)
  718.     ShowCaret( wintext_hWndCopy );
  719.  
  720. ReleaseDC(wintext_hWndCopy,hDC);
  721.  
  722. }
  723.  
  724. void wintext_cursor(int xpos, int ypos, int cursor_type)
  725. {
  726.  
  727. if (wintext_textmode != 2)  /* not in the right mode */
  728.     return;
  729.  
  730.     wintext_cursor_x = xpos;
  731.     wintext_cursor_y = ypos;
  732.     if (cursor_type >= 0) wintext_cursor_type = cursor_type;
  733.     if (wintext_cursor_type < 0) wintext_cursor_type = 0;
  734.     if (wintext_cursor_type > 2) wintext_cursor_type = 2;
  735.     if (wintext_cursor_owned != 0)
  736.         {
  737.         CreateCaret( wintext_hWndCopy, wintext_bitmap[wintext_cursor_type],
  738.               wintext_char_width, wintext_char_height);
  739.               SetCaretPos( wintext_cursor_x*wintext_char_width,
  740.                   wintext_cursor_y*wintext_char_height);
  741.               SetCaretBlinkTime(500);
  742.               ShowCaret( wintext_hWndCopy );
  743.         }
  744.  
  745. }
  746.